package com.cyzy.utils;


import org.apache.commons.lang3.StringUtils;

import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @description: 卡号生成工具
 * @author: Jay
 * @create: 2021-10-22 16:39
 **/
public class CodeNumberUtil {
    private static final AtomicInteger counter = new AtomicInteger(0);
    public static final String NUMBERCHAR = "0123456789";
    public static final String ENGILSHCHAR = "QWERTYUIOPASDFGHJKLZXCVBNM1234567890";

    /**
     * Description: 生成条码（卡号）
     */
    public static String getCodeNumber(String prefix) {
        if (!StringUtils.isEmpty(prefix)) {
            //可以修改生成随机数的长度，生成想要的长度的条码
            String num = generateNumString(6);
            String st = prefix + num + getUnixTime();
            return st + getCardCheckCode(st);
        }
        return "prefix不能为空";
    }

    /**
     * 传入一个前缀和一个码。 【根据自己的业务定义】
     *  卡号
     */
    public static String getCodeNumber(String prefix, String code) {
        if (!StringUtils.isEmpty(prefix) && !StringUtils.isEmpty(code)) {
            String st = prefix + code + getUnixTime();
            return st + getCardCheckCode(st);
        }
        return "prefix和code不能为空";
    }

    /**
     * 校验条码是否正确
     */
    public static boolean checkCode(String code) {
        char bit = getCardCheckCode(code.substring(0, code.length() - 1));
        if (bit == 'N') {
            return false;
        }
        return code.charAt(code.length() - 1) == bit;
    }

    /**
     * 从不含校验位的卡号采用 Luhm 校验算法获得校验位
     */
    private static char getCardCheckCode(String nonCheckCodeCardNo) {
        if (nonCheckCodeCardNo == null
                || nonCheckCodeCardNo.trim().length() == 0
                || !nonCheckCodeCardNo.matches("\\d+")) {
            // 如果传的不是数据返回N
            return 'N';
        }
        char[] chs = nonCheckCodeCardNo.trim().toCharArray();
        int luhmSum = 0;
        for (int i = chs.length - 1, j = 0; i >= 0; i--, j++) {
            int k = chs[i] - '0';
            if (j % 2 == 0) {
                k *= 2;
                k = k / 10 + k % 10;
            }
            luhmSum += k;
        }
        return (luhmSum % 10 == 0) ? '0' : (char) ((10 - luhmSum % 10) + '0');
    }

    /***
     * 获取当前系统时间戳 并截取后8位
     */
    private static String getUnixTime() {
        long timestamp = System.currentTimeMillis();
        int seq = counter.getAndIncrement() % 1000; // 序列号范围 0-999
        return String.format("%tH%tM%tS%03d", timestamp, timestamp, timestamp, seq);
    }

    /**
     * 生成一个定长的纯数字符串
     */
    private static String generateNumString(int length) {
        StringBuffer sb = new StringBuffer();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            sb.append(NUMBERCHAR.charAt(random.nextInt(NUMBERCHAR.length())));
        }
        return sb.toString();
    }

    /*========================================================================================================*/
    /*===============================================激活码====================================================*/
    /*========================================================================================================*/


    /**
     * Description: 生成激活码（密码）
     */
    public static String getCodeEnglish(String prefix) {
        if (!StringUtils.isEmpty(prefix)) {
            //可以修改生成随机数的长度，生成想要的长度的条码
            String num = generateEngString(2);
            String st = prefix + num + getUnixTime();
            return st + getCardCheckCode(st);
        }
        return "prefix不能为空";
    }
    /**
     * 传入一个前缀和一个码。 【根据自己的业务定义】
     *  激活码
     */
    public static String getCodeEnglish(String prefix, String code) {
        if (!StringUtils.isEmpty(prefix) && !StringUtils.isEmpty(code)) {
            String st = prefix + code + getUnixTime();
            return st + getCardCheckCode(st);
        }
        return "prefix和code不能为空";
    }

    /**
     * 生成一个定长混搭
     */

    // 改用 ThreadLocalRandom
    private static String generateEngString(int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int index = ThreadLocalRandom.current().nextInt(ENGILSHCHAR.length());
            sb.append(ENGILSHCHAR.charAt(index));
        }
        return sb.toString();
    }


    //测试卡号
//    public static void main(String[] args) {
//
//        try {
//
//            for (int i = 0; i < 1; i++) {
//                // 生成条码
//                String code = getCodeNumber("99");
//                System.out.println(code);
//                // 检验条码
//                System.out.println(checkCode(code));
//            }
//
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }

    //测试激活码
//    public static void main(String[] args) {
//        try {
//            for (int i = 0; i < 1; i++) {
//                // 生成条码
//                String code = getCodeEnglish("MX","33");
//                System.out.println(code);
//                // 检验条码
//                System.out.println(checkCode(code));
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
}

